(deftemplate UserHasUnit
(declare (from-class prototype.persistence.pojo.UserHasUnit)))

(deftemplate User
(declare (from-class prototype.persistence.pojo.User)))

(deftemplate Position
 (declare (from-class prototype.persistence.pojo.Position)))

(deftemplate Unit
 (declare (from-class prototype.persistence.pojo.Unit)))

(deftemplate JESSHelper
 (declare (from-class prototype.runtime.impl.unit.JESSHelper)))

(defquery search-civils
  "Finds civils in the given radius of the given position"
  (declare (variables ?pn ?ar))
  (UserHasUnit (unit ?unt) (user ?usr) (id ?identity) (position ?p))
  (test (= (getTeam ?usr) 2)) /* CIVIL UNIT? */
  (test (<= (calculateDistance ?pn ?p) ?ar))
)

(deffunction getPosition (?uhu)
    (return ?uhu.position)
)

(deffunction getUser (?uhu)
   (return ?uhu.user)
)

(deffunction getTeam (?usr)
   (return ?usr.team)
)

(deffunction getUnit (?uhu)
    (return ?uhu.unit)
)

(deffunction getFireRange (?unt)
    (return ?unt.rangeDistance)
)

(deffunction getAccuracy (?unt)
    (return ?unt.accuracy)
)

(deffunction getObject (?uhu)
    (return ?uhu.OBJECT)
    )

(deffunction getId (?uhu)
    (return ?uhu.id)
   )

( deffunction calculateDistance (?pos1 ?pos2)
    (return
        (sqrt
            (+ (* (- ?pos1.x ?pos2.x) (- ?pos1.x ?pos2.x))
               (* (- ?pos1.z ?pos2.z) (- ?pos1.z ?pos2.z))
            )
        )
    )
)

(deffunction calculateAccuracyRadius (?me ?distance)
   (return
        (*
            (- 100 (getAccuracy (getUnit ?me)))
            (* ?distance 0.005)
        )
    )
)

(defrule enemy-unit-found-within-fireRange-for-police
	?enemy <- (UserHasUnit (id ?uid1) (position ?ep))
	?me <- (UserHasUnit (id ?uid2) )
        ?civil <- (UserHasUnit (id ?uid3))
        ?jhelper <- (JESSHelper (uhu ?juhu))
        (test (not  (or (= ?uid1 ?uid2)  (= ?uid3 ?uid1) (= ?uid2 ?uid3)))) /*ALL UNITS ARE DIFFERENT*/
        (test (= (getTeam (getUser ?me)) 0))
        (test (= (getTeam (getUser ?civil)) 2))
        (test (= (getTeam (getUser ?enemy)) 1))
        (test (= (getId ?juhu) ?uid2) ) ; calculating fire position for just this uhu
	(test  (not (= (getTeam (getUser ?enemy)) (getTeam (getUser ?me))))) /*IS IT ENEMY UNIT?*/
        (test (<= (calculateDistance (getPosition ?me) (getPosition ?enemy)) (getFireRange (getUnit ?me)))) /*IS IT WITHIN "MY" FIRE RANGE*/
        /* IS CIVIL UNIT NOT IN THE AREA OF THE FIRE EFFECT (FIRE ACCURACY IS CONSIDERED) ?? */
         (test (<= (calculateAccuracyRadius ?me (calculateDistance (getPosition ?me) (getPosition ?enemy))) (calculateDistance (getPosition ?civil) (getPosition ?enemy))))
        =>
        (?jhelper.OBJECT generateFirePosition ?ep.x ?ep.y ?ep.z)
)


(defrule enemy-unit-found-within-fireRange-for-terrorist
	?enemy <- (UserHasUnit (id ?uid1) (position ?ep))
	?me <- (UserHasUnit (id ?uid2) )
        ?civil <- (UserHasUnit (id ?uid3))
        ?jhelper <- (JESSHelper (uhu ?juhu))
        (test (not  (or (= ?uid1 ?uid2)  (= ?uid3 ?uid1) (= ?uid2 ?uid3)))) /*ALL UNITS ARE DIFFERENT*/
        (test (= (getTeam (getUser ?me)) 1))
        (test (= (getTeam (getUser ?civil)) 2))
        (test (= (getTeam (getUser ?enemy)) 0))
        (test (= (getId ?juhu) ?uid2) ) ; calculating fire position for just this uhu
	(test  (not (= (getTeam (getUser ?enemy)) (getTeam (getUser ?me))))) /*IS IT ENEMY UNIT?*/
        (test (<= (calculateDistance (getPosition ?me) (getPosition ?enemy)) (getFireRange (getUnit ?me)))) /*IS IT WITHIN "MY" FIRE RANGE*/
        /* IS CIVIL UNIT NOT IN THE AREA OF THE FIRE EFFECT (FIRE ACCURACY IS CONSIDERED) ?? */
         ;(test (<= (calculateAccuracyRadius ?me (calculateDistance (getPosition ?me) (getPosition ?enemy))) (calculateDistance (getPosition ?civil) (getPosition ?enemy))))
        =>
        (?jhelper.OBJECT generateFirePosition ?ep.x ?ep.y ?ep.z)
)
